/* 
 *  Syntelos XB
 *  Copyright (C) 2006 John Pritchard.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA
 */

package syntelos.xb.at;


/** 
 * <p> Attribute of {@link syntelos.xb.Method} as a list of {@link
 * Variable}'s.
 * 
 * @author jdp
 */
public final class LocalVariableTable 
    extends syntelos.xb.Attribute
{
    public final static java.lang.String ATNAME = "LocalVariableTable";
    public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb/at","xat:local-variable-table");
    
    public LocalVariableTable(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
        super(doc,name);
    }
    public LocalVariableTable(org.w3c.dom.Document doc){
        this(doc,NAME);
    }
    public LocalVariableTable(){
        this(DOC_NIL);
    }

    public syntelos.iou.dom.Node compile(){

        this.getAttributeName().setNodeValue("utf8:LocalVariableTable");

        return super.compile();
    }
    public syntelos.iou.dom.Node decompile(){
        this.getChildNodes2().sort();
        return this;
    }
    protected syntelos.xb.Attributes getAttributeCodeAttributes(){
        return (syntelos.xb.Attributes)this.getParentNode();
    }
    /** @see syntelos.xb.Base
     */
    public syntelos.xb.at.LocalVariableTable getAttributeLocalVariableTable(){
        return this;
    }
    /** @see syntelos.xb.Base
     */
    public Code getAttributeCode(){
        return (Code)(this.getParentNode().getParentNode());
    }
    /** @see syntelos.xb.Base
     */
    public syntelos.xb.op.Code getOpCode(){
        return this.getAttributeCode().getOpCode();
    }
    /** @see syntelos.xb.Base
     */
    public syntelos.xb.Method getMethod(){
        return this.getAttributeCode().getMethod();
    }
    public Variable getVar(int slot){
        if (this.hasChildNodes())
            return (Variable)this.getChildById(new java.lang.Integer(slot),this);
        else
            return null;
    }
    public Variable getVar(syntelos.xb.IO.Uri uri){
        if ("variable".equals(uri.getSchemeHead())){
            Variable var;
            java.lang.String name_string = uri.getPath();
            java.lang.String slot_string = uri.getQuery("slot");
            if (null != slot_string){
                int slot = syntelos.xb.IO.Uri.Integer(slot_string);
                var = this.getVar(slot);
                if (null != var){
                    if (null != name_string){
                        syntelos.xb.Name var_name = var.getName(false);
                        if (null != var_name){
                            syntelos.xb.CF.Constants.Utf8 var_name_const =
                                var_name.getNameConst();
                            if (null != var_name_const &&
                                name_string.equals(var_name_const.getString()))
                                {
                                    return var;
                                }
                        }
                    }
                    else
                        return var;
                }
            }
            var = (Variable)this.getChildByField("name",name_string);
            if (null != var)
                return var;
            else {
                var = new Variable();
                this.appendChild(var);
                if (var.define(uri)){
                    int slot = (this.getChildNodes2().getLength())-(1);
                    var.setId(slot);
                    if (var != this.getVar(slot))
                        throw new syntelos.xb.Error.Bug();
                    else
                        var.getSlot().setSlot(slot);
                }
                return var;
            }
        }
        else
            throw new syntelos.xb.Error.Argument(uri.toString());
    }
    public int getVarSlot(syntelos.xb.IO.Uri uri){
        Variable var = this.getVar(uri);
        return var.getSlot().getSlot();
    }
    public int getSlot(Variable var){
        if (null == var)
            throw new java.lang.IllegalArgumentException();
        else {
            Variable.Slot slot = var.getSlot();
            if (null != slot)
                return slot.getSlot();
            else
                return this.getChildNodes2().item(var);
        }
    }
    public int atlen(){
        int count = this.countChildNodes();
        return (2 + (10 * count));
    }
    public void readCF(syntelos.xb.IO.Uri src, syntelos.xb.CF.Reader reader)
        throws java.io.IOException
    {
        org.w3c.dom.Document doc = this.getOwnerDocument();
        int at_length = reader.readInt();
        int var_count = reader.readUnsignedShort();
        Variable var;
        for (int var_idx = 0; var_idx < var_count; var_idx++){
            var = new Variable(doc);
            this.appendChild(var);
            var.readCF(src,reader);
        }
    }
    public void writeCF(syntelos.xb.IO.Uri dst, syntelos.xb.CF.Writer writer)
        throws java.io.IOException
    {
        this.getAttributeName().writeCF(dst,writer);
        int at_len =  this.atlen();
        writer.writeInt(at_len);
        int count = this.countChildNodes();
        writer.writeShort(count);
        if (0 < count){
            org.w3c.dom.NodeList children = this.getChildNodes();
            Variable var;
            for (int idx = 0; idx < count; idx++){
                var = (Variable)children.item(idx);
                var.writeCF(dst,writer);
            }
        }
    }
}
